<?PHP

error_reporting(E_ALL);
// $Id: Exp$

/**
 * DpTable Class.
 *
 *
 *  <p>OO table display class.</p>
 *
 *  <p>Initialize with a result-set-type array.</p>
 * </p>Use the AddColumn method to accumulate column information.
 *  <p>Sorting. We have a choice of sorting in the query, or sorting the array.
Sorting in the query might be marginally quicker, but it means contorting the
SQL statement, which increases coupling, and makes the query more complicated
(bad) and less general and reusable (bad). So we'll do sorting in the array.

This also anticipates adding report manipulation to the client,
as JavaScript becomes more standard (e.g. Ajax, DHTML, etc.)
 */

/*
Pending PHP5 -
Private properties/methods are named with a preceding underline.
Do not reference them externally - they will be hidden.
*/


class DpTable
{
    private $_table_caption;
    private $_align;
    private $_sortcol;
    private $_AorD;
    private $_attributes;
    private $_captions   = array() ;
    private $_columns    = array() ;
    private $_rows       = array() ;  // Array for rows e.g. resultset.
    private $_style_id;

    /**
     * Constructor.
     *
     */

    public function DpTable($attributes = "")
    {
        $this->_attributes = $attributes;
    }

    /**
     * setRows. Argument is resultset-type array (colname => value).
     * 
     */

    public function SetRows($rows)
    {
        $this->_rows = $rows;
    }

    public function DumpRows()
    {
        var_dump( $this->_rows ) ;
    }

    public function RowCount()
    {
        return count($this->_rows ) ;
    }

    /**
     * addColumn.  
     * 
     * 
     */

    public function addColumn( 
                        $caption,
                        $colname,
                        $template = null,
                        $styleid = null)
    {
        $this->_columns[] = new DpTableColumn(
                        $caption, 
                        $colname,
                        $template,
                        $styleid);
    }

    public function SetStyle($styleid)
    {
        $this->_style_id = $styleid;
    }

    /**
     * setSort. Arguments: Column name, and A or D.
     * Used to indicate, when a column heading is clicked,
     * which sort direction should be specified. In future
     * this should be accomplished in the array, not the query;
     * saving a database hit (and time and bandwidth).
     *
     */

    public function SetSort($sortcol, $AorD)
    {
        $this->_sortcol = $sortcol;
        $this->_AorD = $AorD;
    }

    /**
     * echo. Generate the report.
     *
     */

    public function EchoTableNumbered()
    {
        $this->EchoTable(true) ;
    }

    /**
     * addCaption. Add a superheader above the header row.
     *
     */

    public function AddCaption( $text, $ncol = 1 )
    {
        $this->_captions[] = new DpTableCaption( $text, $ncol ) ;
    }

    public function EchoTable($isnumbered = false)
    {
        if(empty($this->_attributes)) {
            echo "<table border='1' class='dptable'>\n";
        }
        else {
            echo "<table $this->_attributes>\n";
        }

        if(! empty($this->_table_caption)) {
            echo "<caption>$this->_table_caption</caption>\n";
        }
        echo "<tbody>\n";
        $this->_echo_captions($isnumbered);


        $odd_even = true;
        $i = 0;

        foreach($this->_rows as $row)
        {
            if(++$i % 2 == 1 ) {
                $odd_even = !$odd_even;
            }
            if($odd_even)
                echo "<tr class='odd'>\n";
            else
                echo "<tr>\n";
            if($isnumbered) {
                echo "<td>$i</td>\n";
            }
            foreach($this->_columns as $col)
            {
                $col->EchoCell($row);
            }
            echo "</tr>\n";
        }
        echo "</tbody>
            </table>\n";
    }

    /**
     * _echo_captions.
     *
     */

    private function _echo_captions($isnumbered)
    {
        if( count( $this->_captions ) > 0 )
        {
            echo "<tr>\n";
            if( $isnumbered ) {
                echo "<th> &nbsp;</th>\n";
            }
            foreach( $this->_captions as $cap )
            {
                $cap->EchoCaption() ;
            }
            echo "</tr>\n";
        }
                
            
        echo "<tr>\n";
        if($isnumbered)
            echo "<th> &nbsp;</th>\n";
        foreach($this->_columns as $col) {
            $col->echoCaption($this->_sortcol == $col->colName());
        }
        echo "</tr>\n";
    }

    /**
     * _echo_row($row).
     *
     */

    private function _echo_row($row, $rownum = 0)
    {
        echo "<tr>\n";
        if($rownum)
            echo "<td>$rownum</td>\n";
        foreach($this->_columns as $col) {
            $col->EchoCell($row);
        }
        echo "</tr>\n";
    }
}   // end class DpTable

///////////////////////////////////////////////////////////////////////

/**
     * DpTableColumn class.
     */

///////////////////////////////////////////////////////////////////////

class DpTableCaption
{
    private $_caption;
    private $_colcount ;
    private $_align;

    public function DpTableCaption( $caption, $colcount = 1 )
    {
        $this->_caption = $caption ;
        $this->_colcount = $colcount ;
        $this->_set_align( $caption ) ;
    }

    private function _set_align($cap)
    {
        if(! $cap ) return ;
        switch($cap[0])
        {
            default :
                $this->_align = "" ;
                $this->_caption = $cap ;
                return ;
            case '<' :
                $this->_align = " style='text-align: left'";
                break ;
            case '>' :
                $this->_align = " style='text-align: right'";
                break ;
            case '^' :
                $this->_align = " style='text-align: center'";
                break ;
        }
        $this->_caption = substr( $cap, 1 ) ;
    }

    public function EchoCaption()
    {
        echo "<th$this->_align" ;
        if( $this->_colcount > 1 ) {
            echo " colspan='{$this->_colcount}'";
        }
        echo ">{$this->_caption}</th>\n";
    }
}

class DpTableColumn
{
    private $_caption;
    private $_colname;
    private $_template;
    private $_sortAorD;
    private $_sortcol;
    private $_style_id = null;
    private $_issort;
    private $_align;

    /**
        Initializer.

        caption is text column heading.
        colname is the name of the field in the resultset row.
        template is one of:
            a. empty - the cell value is echoed.
            b. an "sprintf" format string, optionally including "%s" for the
                cell value.
            c. if colname is empty, a function to echo any string derivable from the $row. Notice
               a colname for the column is redundant.
        styleid is (naturally enough) the name of the css style to use.
        ishidden - hidden column?
        Public.
     */

    function DpTableColumn(
                $caption, 
                $colname, 
                $template = null, 
                $styleid = null) 
    {
        $this->_colname = $colname;
        $this->_template = $template;
        $this->_style_id = $styleid;

        $this->_set_align($caption) ;
    }


    private function _sort_A_or_D()
    {
        if(!$this->_issort)
            return $this->_sortAorD;
        else
            return ($this->_sortAorD == 'A' ? 'D' : 'A');
    }

    private function _set_align($cap)
    {
        switch($cap[0])
        {
            default :
                $this->_align = "" ;
                $this->_caption = $cap ;
                return ;
            case '<' :
                $this->_align = " style='text-align: left'";
                break ;
            case '>' :
                $this->_align = " style='text-align: right'";
                break ;
            case '^' :
                $this->_align = " style='text-align: center'";
                break ;
        }
        $this->_caption = substr( $cap, 1 ) ;
    }

    public function EchoCaption()
    {

        echo "<th$this->_align> $this->_caption</th>\n";
    }

    public function EchoCell($row)
    {
        $cname = $this->_colname;

        if( is_callable( $this->_template ) ) {
            if( is_array( $row ) && isset( $row[$cname]) ) {
                $str = call_user_func($this->_template, $row[$cname]);
            }
            else {
                // $str = $this->_template();
                if( is_array( $row ) && isset( $row[$cname]) ) {
                    $str = call_user_func($this->_template, $row[$cname] ) ;
                }
                else {
                    $str = call_user_func($this->_template, $row ) ;
                }
            }
        }

        elseif( is_string( $this->_template ) ) {
            if( is_array( $row ) && isset( $row[$cname]))
                $str = sprintf($this->_template, $row[$cname] ) ;
            else
                $str = "" ;
        }
        else {
            if( is_array( $row ) && isset( $row[$cname]))
                $str = $row[$cname] ;
            else
                $str = "" ;
        }
        echo "<td$this->_align>$str</td>\n";
    }

    public function ColName()
    {
        return $this->_colname;
    }
} // end DpTableColumn

?>
